﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSharpExt.Text
{
    public class FastStringBuilder
    {
        private char[] _buffer;
        private int _size;
        private int _length;

        public FastStringBuilder()
        {
            _buffer = new char[_size = 1024];
            _length = 0;
        }

        public FastStringBuilder(int bufferSize)
        {
            _buffer = new char[_size = bufferSize];
            _length = 0;
        }

        public int Length
        {
            get { return _length; }
        }

        public FastStringBuilder Remove(int dummy1, int dummy2)
        {
            _length = 0;
            return this;
        }

        public FastStringBuilder Append(char ch)
        {
            try
            {
                _buffer[_length++] = ch;
            }
            catch (IndexOutOfRangeException)
            {
                char[] newBuffer = new char[_buffer.Length + _size];
                Array.Copy(_buffer, newBuffer, _buffer.Length);
                _buffer = newBuffer;
                _buffer[_length - 1] = ch;
            }
            return this;
        }

        public FastStringBuilder Append(String str)
        {
            for (int i = 0; i < str.Length; ++i)
                Append(str[i]);
            return this;
        }


        public override String ToString()
        {
            return new string(_buffer, 0, _length);
        }

        public int ToInteger()
        {
            bool isNegative = false;
            int at = 0;
            int value = 0;
            char ch = _buffer[at];

            if (ch == '-')
            {
                ++at;
                isNegative = true;
            }
            else if (ch == '+')
            {
                ++at;
            }

            for (ch = _buffer[at]; at < _length; ch = _buffer[++at])
            {
                value = value * 10 + (ch - '0');
            }

            return isNegative ? -value : value;
        }

        public long ToLong()
        {
            bool isNegative = false;
            int at = 0;
            long value = 0;
            char ch = _buffer[at];

            if (ch == '-')
            {
                ++at;
                isNegative = true;
            }
            else if (ch == '+')
            {
                ++at;
            }

            for (ch = _buffer[at]; at < _length; ch = _buffer[++at])
            {
                value = value * 10 + (ch - '0');
            }

            return isNegative ? -value : value;
        }

        public float ToFloat()
        {
            bool isNegative = false;
            bool isDecimal = false;
            int at = 0;
            float value = 0;
            float fraction = 0.1f;

            char ch = _buffer[at];

            if (ch == '-')
            {
                ++at;
                isNegative = true;
            }
            else if (ch == '+')
            {
                ++at;
                isNegative = false;
            }
            else if (ch == '.')
            {
                ++at;
                isDecimal = true;
            }

            if (!isDecimal)
                for (ch = _buffer[at]; at < _length; ch = _buffer[++at])
                {
                    if (ch == '.')
                    {
                        ++at;
                        isDecimal = true;
                        break;
                    }

                    value = value * 10 + (ch - '0');
                }

            if (isDecimal)
                for (ch = _buffer[at]; at < _length; ch = _buffer[++at])
                {
                    value = value + (fraction * (ch - '0'));
                    fraction = fraction / 10;
                }

            value = (float) Math.Round(value, 6);

            return isNegative ? -value : value;
        }

        public double ToDouble()
        {
            bool isNegative = false;
            bool isDecimal = false;
            int at = 0;
            double value = 0;
            double fraction = 0.1;

            char ch = _buffer[at];

            if (ch == '-')
            {
                ++at;
                isNegative = true;
            }
            else if (ch == '+')
            {
                ++at;
                isNegative = false;
            }
            else if (ch == '.')
            {
                ++at;
                isDecimal = true;
            }

            if (!isDecimal)
                for (ch = _buffer[at]; at < _length; ch = _buffer[++at])
                {
                    if (ch == '.')
                    {
                        ++at;
                        isDecimal = true;
                        break;
                    }

                    value = value * 10 + (ch - '0');
                }

            if (isDecimal)
                for (ch = _buffer[at]; at < _length; ch = _buffer[++at])
                {
                    value = value + (fraction * (ch - '0'));
                    fraction = fraction / 10;
                }

            value = (float)Math.Round(value, 6);

            return isNegative ? -value : value;
        }

        public bool ToBoolean()
        {
            return _buffer[0] == 't' || _buffer[0] == 'T';
        }

    }
}
